<template>
  <view :style="[customStyle]" class="u-popup-box">
    <u-input
      v-if="!multiple"
      v-model="label"
      :disabled="disabled"
      :border="border"
      type="select"
      @click="handleSingleClick"
    />
    <u-input-multiple
      v-else
      v-model="label"
      :disabled="disabled"
      :border="border"
      @click="handleMultipleClick"
      @select="handleSelectItem"
      @delete="handleDeleteItem"
    ></u-input-multiple>
    <u-select
      ref="popup-component"
      v-if="componentName === 'u-select'"
      :mode="mode"
      v-model:modelValue="show"
      :list="options"
      @confirm="handleConfirm"
    >
    </u-select>
    <u-cascader-asymmetric
      ref="popup-component"
      v-if="componentName === 'u-cascader-asymmetric'"
      :mode="mode"
      :pickValue="currentValue"
      v-model:modelValue="show"
      :list="options"
      :fieldNames="fieldNames"
      @confirm="handleConfirm"
    >
    </u-cascader-asymmetric>
  </view>
</template>

<script>
  import mpConfig from '../../libs/mixin/mp-vertual-node.js';
  /**
   * u-popup-box 封装弹出窗
   * @description 封装弹出层及回显
   * @property {String,Number} value 值
   * @property {String,Number} modelValue 值
   * @property {String} componentName 弹出层组件名称
   * @property {String} mode 类型
   * @property {Array} options 下拉框值
   * @property {Boolean} disabled 是否禁用输入框(默认false)
   * @property {Boolean} border 是否有边框
   */
  export default {
    name: 'u-popup-box',
    options: mpConfig,
    emits: ['update:modelValue', 'update:value', 'input'],
    props: {
      value: {
        type: [String, Number],
      },
      modelValue: {
        type: [String, Number],
      },
      componentName: {
        type: String,
        default: 'u-select',
      },
      mode: {
        type: String,
        default: 'single-column',
      },
      options: {
        type: Array,
        default: () => {
          return [];
        },
      },
      disabled: {
        type: Boolean,
        default: false,
      },
      border: {
        type: Boolean,
        default: true,
      },
      multiple: {
        type: Boolean,
        default: false,
      },
      fieldNames: {
        type: Object,
        default: () => {
          return {
            children: 'children',
            label: 'label',
            value: 'value',
          };
        },
      },
    },
    data() {
      return {
        show: false,
        currentIndex: -1,
        currentValue: [],
      };
    },
    computed: {
      fieldNamesComplete() {
        const { children, label, value } = this.fieldNames;
        return {
          children: children ?? 'children',
          label: label ?? 'label',
          value: value ?? 'value',
        };
      },
      keyValueMap() {
        const keyMap = {};
        // 获取映射字段
        const { children: childrenKey, value: valueKey } = this.fieldNamesComplete;
        const recursion = (list, parent, callback) => {
          list.forEach((item) => {
            callback(item, parent);
            if (item[childrenKey] && item[childrenKey].length > 0) {
              recursion(item[childrenKey], item, callback);
            }
          });
        };
        recursion(this.options, null, (item, parent) => {
          keyMap[item[valueKey]] = {
            ...item,
            parent,
          };
        });
        return keyMap;
      },
      label() {
        // #ifndef VUE3
        const value = this.value;
        // #endif

        // #ifdef VUE3
        const value = this.modelValue;
        // #endif
        if (!value || !this.keyValueMap) {
          return value;
        }
        // 获取映射字段
        const { children: childrenKey, value: valueKey, label: labelKey } = this.fieldNamesComplete;
        switch (this.mode) {
          case 'single-column':
            return this.keyValueMap[value] ? this.keyValueMap[value][labelKey] : value;
          case 'cascader': {
            const result = [];
            value.forEach((item) => {
              result.push(this.keyValueMap[item] ? this.keyValueMap[item][labelKey] : item);
            });
            return result.join(' / ');
          }
          case 'tree': {
            let result;
            if (this.multiple) {
              // 多选的情况下，获取每个label
              result = [];
              value.forEach((item) => {
                result.push(this.keyValueMap[item] ? this.keyValueMap[item][labelKey] : item);
              });
            } else {
              result = this.keyValueMap[value] ? this.keyValueMap[value][labelKey] : value;
            }
            return result;
          }
          default: {
            const result = [];
            value.forEach((item) => {
              result.push(
                this.keyValueMap[item[valueKey]]
                  ? this.keyValueMap[item[valueKey]]
                  : item[valueKey],
              );
            });
            return result;
          }
        }
      },
    },
    watch: {},
    mounted() {},
    methods: {
      // 单选是新增逻辑
      handleSingleClick() {
        this.show = true;
        // #ifndef VUE3
        const value = this.value;
        // #endif

        // #ifdef VUE3
        const value = this.modelValue;
        // #endif

        this.currentValue = value;
      },
      // 处理多选新增逻辑
      handleMultipleClick() {
        // 多选新增时，弹窗Value置为空
        this.currentValue = [];
        this.currentIndex = -1;
        this.show = true;
      },
      // 处理多选编辑逻辑
      handleSelectItem(index) {
        // 当前操作项设置为选中的项
        this.currentValue = this.modelValue[index];
        this.currentIndex = index;
        this.show = true;
      },
      // 处理多选删除逻辑
      handleDeleteItem(index) {
        // #ifndef VUE3
        const value = this.value;
        // #endif

        // #ifdef VUE3
        const value = this.modelValue;
        // #endif
        value.splice(index, 1);
        this.$emit('input', value);
        this.$emit('update:value', value);
        this.$emit('update:modelValue', value);
      },
      handleConfirm(option) {
        const { children: childrenKey, value: valueKey, label: labelKey } = this.fieldNamesComplete;
        switch (this.mode) {
          case 'single-column':
            this.$emit('input', option[0][valueKey]);
            this.$emit('update:value', option[0][valueKey]);
            this.$emit('update:modelValue', option[0][valueKey]);
            break;
          case 'tree': {
            let result;
            // 如果是多选
            if (this.multiple) {
              // #ifndef VUE3
              const value = this.value;
              // #endif
              // #ifdef VUE3
              const value = this.modelValue;
              // #endif
              let _result = option[option.length - 1][valueKey];
              // 排除子节点未选的问题
              if (!_result) {
                _result = option[option.length - 2][valueKey];
              }

              if (this.currentIndex !== -1) {
                // 修改
                value[this.currentIndex] = _result;
              } else {
                // 新增
                value.push(_result);
              }

              // 去重
              result = [...new Set(value)];
            } else {
              // 单选，获取最后一个节点
              let _result = option[option.length - 1][valueKey];
              // 排除子节点未选的问题
              if (!_result) {
                _result = option[option.length - 2][valueKey];
              }
              result = _result;
            }
            this.$emit('input', result);
            this.$emit('update:value', result);
            this.$emit('update:modelValue', result);
            break;
          }
          default: {
            const result = [];
            option.forEach((item) => {
              result.push(item[valueKey]);
            });
            this.$emit('input', result);
            this.$emit('update:value', result);
            this.$emit('update:modelValue', result);
          }
        }
      },
    },
  };
</script>

<style scoped lang="scss">
  @import '../../libs/css/style.components.scss';

  .u-popup-box {
    /* #ifndef APP-NVUE */
    display: block;
    /* #endif */
    width: 100%;
  }
</style>
